{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "#-*-coding:utf-8 -*-\n",
    "#所有需要的库文件添加该处\n",
    "import pandas as pd\n",
    "import  numpy as np\n",
    "import os\n",
    "import sys\n",
    "from datetime import datetime,timedelta,date\n",
    "from pyecharts import Line,Kline,Bar,Overlap,Grid\n",
    "from jqdatasdk import *\n",
    "\n",
    "sys.path.append('C:\\\\quanttime\\\\src\\\\comm\\\\')\n",
    "import trade_date_util\n",
    "\n",
    "pd.set_option('precision',3)\n",
    "auth('13811866763', \"sam155\")  # jqdata 授权"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>display_name</th>\n",
       "      <th>name</th>\n",
       "      <th>start_date</th>\n",
       "      <th>end_date</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>000001.XSHG</th>\n",
       "      <td>上证指数</td>\n",
       "      <td>SZZS</td>\n",
       "      <td>1991-07-15</td>\n",
       "      <td>2200-01-01</td>\n",
       "      <td>index</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>000002.XSHG</th>\n",
       "      <td>A股指数</td>\n",
       "      <td>AGZS</td>\n",
       "      <td>1992-02-21</td>\n",
       "      <td>2200-01-01</td>\n",
       "      <td>index</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            display_name  name start_date   end_date   type\n",
       "000001.XSHG         上证指数  SZZS 1991-07-15 2200-01-01  index\n",
       "000002.XSHG         A股指数  AGZS 1992-02-21 2200-01-01  index"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "index_dir = \"C:\\\\quanttime\\\\data\\\\index\\\\jq\\\\\"\n",
    "# 获取所有的指数标的\n",
    "index_security = get_all_securities(types=['index'], date=None)\n",
    "# 滤除退市的，或者当前不存在的指数\n",
    "index_security = index_security[index_security[\"end_date\"] == \"2200-01-01\"]\n",
    "index_security.head(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 设置比较基准,front_buy:与前front_buy进行比较，如果高则买入，与end_sell比较，如果低则卖出\n",
    "front_buy = 20\n",
    "end_sell = 20"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'numpy.ndarray' object has no attribute 'head'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-6-8a88e5ab4a3a>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;31m# 获取所有交易日\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[0mtrade_date\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mget_all_trade_days\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mtrade_date\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhead\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'numpy.ndarray' object has no attribute 'head'"
     ]
    }
   ],
   "source": [
    "# 获取所有交易日 [numpy.ndarray],元素为datetime.date\n",
    "trade_date = get_all_trade_days()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_trade_signal(code, date):\n",
    "    '''\n",
    "    获取交易信号，输入指数的code，起始日期\n",
    "    例如获取date=2019-6-1 的交易信号\n",
    "    '''\n",
    "    file = index_dir + code + '.csv'\n",
    "    df = pd.read_csv(file, index_col=[\"date\"], parse_dates=True, usecols=[\"date\", \"close\"])\n",
    "    \n",
    "    list_date = get_trade_date_by_count(date, front_buy)\n",
    "    pre_20 = list_date[0]\n",
    "    pre_1 = list_date[-2]\n",
    "    if (pre_1 not in df.index) or (pre_20 not in df.index):\n",
    "        return \"unkown\"\n",
    "    try:\n",
    "        close_1 = df.loc[pre_1,[\"close\"]][\"close\"]\n",
    "        close_20 = df.loc[pre_20,[\"close\"]][\"close\"]\n",
    "    except KeyError:\n",
    "        return \"unkown\"\n",
    "    if close_1 > close_20:\n",
    "        return \"buy\"\n",
    "    elif close_1 < close_20:\n",
    "        return \"sell\"\n",
    "    else:\n",
    "        return \"hold\"\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "def process_trade_result(list_record):\n",
    "    '''\n",
    "    处理交易结果\n",
    "    '''\n",
    "    list_trade_point = []\n",
    "    for pos, dic in enumerate(list_record):   \n",
    "        dic_key = dic.keys()[0]\n",
    "        dic_value = dic.values()[0]\n",
    "        trade_direct = dic_key.split('_')[0]\n",
    "        trade_date = dic_key.split('_')[1]\n",
    "        if pos == 0:\n",
    "            if trade_direct != \"buy\":\n",
    "                print(\"本次交易记录有误，record：%r\" % list_record)\n",
    "                return\n",
    "        if pos % 2 == 0:\n",
    "            if trade_direct != \"buy\":\n",
    "                print(\"本次交易记录有误，record：%r\" % list_record)\n",
    "                return\n",
    "        else:\n",
    "            if trade_direct != \"sell\":\n",
    "                print(\"本次交易记录有误，record：%r\" % list_record)\n",
    "                return\n",
    "        list_trade_point.append(dic_value)\n",
    "    list_diff = []\n",
    "    for i in range(int(len(list_trade_point) / 2)):\n",
    "        front = list_trade_point.pop(0)\n",
    "        end = list_trade_point(0)\n",
    "        diff = (end - front)/ front\n",
    "        list_diff.append(diff)\n",
    "    result = 1\n",
    "    for i in list_diff:\n",
    "        result = result * (1 + i)\n",
    "    return result      "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_trade_date_by_count(start_date, count):\n",
    "    '''\n",
    "    根据指定的起始日期，往前推count天\n",
    "    这里往前推的日期不包括start_date，也就是从start_date的前一天开始计算\n",
    "    :param start_date: datetime，date，str\n",
    "    :param count: int 天\n",
    "    :return: list date类型\n",
    "    '''\n",
    "    start = to_date(start_date)\n",
    "    if start is None:\n",
    "        return start_date\n",
    "    trade_date_file = r'C:\\quanttime\\data\\basic_info\\all_trade_day.csv'\n",
    "    trade_date = pd.read_csv(trade_date_file, index_col=[\"trade_date\"], parse_dates=True)\n",
    "    list_trade_date = trade_date.index.tolist()\n",
    "    list_trade_date = [d.date() for d in list_trade_date]\n",
    "    return [d for d in list_trade_date if d <= start][-count-1:]\n",
    "\n",
    "# =========================\n",
    "\n",
    "\n",
    "def to_date(input_date):\n",
    "    '''\n",
    "    convert_date('2015-1-1')\n",
    "    datetime.date(2015, 1, 1)\n",
    "\n",
    "    convert_date('2015-01-01 00:00:00')\n",
    "    datetime.date(2015, 1, 1)\n",
    "\n",
    "    convert_date(datetime.datetime(2015, 1, 1))\n",
    "    datetime.date(2015, 1, 1)\n",
    "\n",
    "    convert_date(datetime.date(2015, 1, 1))\n",
    "    datetime.date(2015, 1, 1)\n",
    "    '''\n",
    "    if is_str(input_date):\n",
    "        if ':' in input_date:\n",
    "            input_date = input_date[:10]\n",
    "        return datetime.strptime(input_date, '%Y-%m-%d').date()\n",
    "    elif isinstance(input_date, datetime):\n",
    "        return input_date.date()\n",
    "    elif isinstance(input_date, date):\n",
    "        return input_date\n",
    "    elif input_date is None:\n",
    "        return None\n",
    "\n",
    "\n",
    "def is_str(s):\n",
    "    return isinstance(s, str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1992-01-11 00:00:00\n",
      "2019-06-16 16:25:05.239882\n"
     ]
    },
    {
     "ename": "IndexError",
     "evalue": "list index out of range",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-48-39853a1d14da>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m     15\u001b[0m     \u001b[0mlist_trade_date\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtrade_date_util\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_trade_date_range2\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstart\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0myesterday\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     16\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mst\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mlist_trade_date\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 17\u001b[1;33m         \u001b[0msignal\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mget_trade_signal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mst\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     18\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0msignal\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m\"buy\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mand\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mposition\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     19\u001b[0m             \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-42-f38bf319f960>\u001b[0m in \u001b[0;36mget_trade_signal\u001b[1;34m(code, date)\u001b[0m\n\u001b[0;32m      9\u001b[0m     \u001b[0mlist_date\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mget_trade_date_by_count\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdate\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfront_buy\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     10\u001b[0m     \u001b[0mpre_20\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlist_date\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m     \u001b[0mpre_1\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlist_date\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     12\u001b[0m     \u001b[1;32mif\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mpre_1\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mdf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mor\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mpre_20\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mdf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     13\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[1;34m\"unkown\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mIndexError\u001b[0m: list index out of range"
     ]
    }
   ],
   "source": [
    "list_trade_result_record = []\n",
    "# position:0 空仓，1 持仓\n",
    "position = 0\n",
    "for code in index_security.index[0:2]:\n",
    "    start_date = index_security.loc[code,[\"start_date\"]][\"start_date\"]\n",
    "    start = start_date + timedelta(days=180)\n",
    "    file = index_dir + code + '.csv'\n",
    "    df = pd.read_csv(file, index_col=[\"date\"], parse_dates=True, usecols=[\"date\", \"open\"])\n",
    "    if start > datetime.today():\n",
    "        print(\"指数开始的时间过于接近当前日期，暂时不统计，start_date:%s\" % str(start_date))\n",
    "        continue\n",
    "    yesterday = datetime.today() - timedelta(days=1)\n",
    "    print(start)\n",
    "    print(yesterday)\n",
    "    list_trade_date = trade_date_util.get_trade_date_range2(start, yesterday)\n",
    "    for st in list_trade_date:\n",
    "        signal = get_trade_signal(code, st)\n",
    "        if (signal == \"buy\") and (position == 0):\n",
    "            try:\n",
    "                buy_price = df.loc[st,[\"open\"]][\"open\"]\n",
    "                list_trade_result_record.append({'buy_' + str(st): buy_price})\n",
    "            except KeyError:\n",
    "                print(\"date:%s 没有对应的指数值\" % str(st))\n",
    "        elif (signal == \"sell\") and (position == 1):\n",
    "            try:\n",
    "                sell_price = df.loc[st,[\"open\"]][\"open\"]\n",
    "                list_trade_result_record.append({'sell_' + str(st): sell_price})\n",
    "            except KeyError:\n",
    "                print(\"date:%s 没有对应的指数值\" % str(st))\n",
    "        else:\n",
    "            print(\"date:%s 指数相对20天前没有变化或获取的状态未知\" % str(st))\n",
    "    result = process_trade_result(list_trade_result_record)\n",
    "    print(result)\n",
    "            \n",
    "    \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "list index out of range",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-51-7a8fd8ab77a4>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[0mtmp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mtmp\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mIndexError\u001b[0m: list index out of range"
     ]
    }
   ],
   "source": [
    "tmp = [1,2,3]\n",
    "tmp[-4]"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
